﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using TestXNA3.Resources.Shaders;
using Microsoft.Xna.Framework;
using XMas;
using TestXNA3.Render;

namespace TestXNA3.Resources.Meshes
{
    public class SkeletalMesh : MeshResource
    {
        
        public Model Mesh = null;
        public CSkeletonData SkinData = null;
        public Matrix[] BoneList;
        public XMAnimationSystem AnimTree = null;

        private struct SkeletalMeshDesc
        {
            public string MeshName;
            public Model Mesh;
            public CSkeletonData SkinData;
        };

        private static List<SkeletalMeshDesc> _cachedMeshes = null;

        public SkeletalMesh(string meshName, string animTreeName)
        {
            SetSkeletalMesh(meshName);
            SetAnimTree(animTreeName);
        }

        public void SetAnimTree(string animTreeName)
        {
            try
            {
                AnimTree = XMAnimationSystem.LoadFromFile(TestConfig.ContentPath + "\\AnimTrees\\" + animTreeName + ".xmas", SkinData, null);
            }
            catch
            {
                Logger.Print("Can't find anim tree " + animTreeName);
            }
        }

        public void SetSkeletalMesh(string meshName)
        {
            meshName = TestConfig.ContentPath + "SkeletalMeshes/" + meshName;
            if (_cachedMeshes == null)
            {
                _cachedMeshes = new List<SkeletalMeshDesc>();
            }
            try
            {
                SetModel(meshName);
            }
            catch
            {
                Logger.Print("Can't find skeletal mesh " + meshName);
            }
            Shader = new SkeletalMeshDefaultShader();
        }

        private void SetSkeletalMeshByDesc(SkeletalMeshDesc desc)
        {
            Mesh = desc.Mesh;
            SkinData = desc.SkinData;
        }

        private void SetModel(string meshName)
        {
            foreach (SkeletalMeshDesc desc in _cachedMeshes)
            {
                if (desc.MeshName == meshName.ToLower())
                {
                    SetSkeletalMeshByDesc(desc);
                    return;
                }
            }

            Model skeletalMesh = GameStartup.ContentManager.Load<Model>(meshName);
            if (skeletalMesh != null)
            {
                SkeletalMeshDesc desc = new SkeletalMeshDesc();
                desc.MeshName = meshName.ToLower();
                desc.Mesh = skeletalMesh;
                desc.SkinData = skeletalMesh.Tag as CSkeletonData;
                SetSkeletalMeshByDesc(desc);
                _cachedMeshes.Add(desc);
            }
        }

        public override void Render(ref Microsoft.Xna.Framework.Matrix view, ref Microsoft.Xna.Framework.Matrix proj, ref Microsoft.Xna.Framework.Vector3 ViewerLocation, TestXNA3.Render.SceneRenderer.EDrawMode drawMode)
        {
            BoneList = AnimTree.GetSkinTransforms();
            ((SkeletalMeshDefaultShader)Shader).BoneList = BoneList;
            Shader.World = World;
            Shader.View = view;
            Shader.Projection = proj;
            Shader.EyePosition = new Vector4(ViewerLocation, 1.0f);
            Shader.SetTechnique(drawMode);
            Shader.ApplyShaderConst();

            DrawDefaultModel(Mesh);
        }
    }
}
